/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "Creator.h"
#include "Renderer.h"
#include <logs/Log.h>
#include <vector>
#include <win32/win32.h>
#include <d3d8.h>

namespace liba
{
namespace lib2d
{
namespace hard
{
namespace directx8
{

static HINSTANCE d3d8_dll = 0;
static IDirect3D8 * (__stdcall *direct_create_8) ( UINT SDKVersion ) = 0;
static LPDIRECT3D8 direct3d = 0;
static std::vector< Renderer * > * renderers = 0;

Creator::Creator()
{
	if( renderers )
		throw Gluck(__FUNCTION__, "Renderers already exists");

	logs::log() << __FUNCTION__ << "Creating Renderers\n";
	renderers = new std::vector< Renderer * >();

	d3d8_dll = LoadLibrary("D3D8.DLL");
	if( !d3d8_dll )
	{
		logs::log() << logs::error << "In lib3d::hard::directx8::create(): DirectX is lower than 8\n";
		return;
	}

	direct_create_8 = (IDirect3D8 * (__stdcall *) ( UINT SDKVersion ))GetProcAddress (d3d8_dll, "Direct3DCreate8");
	if ( !direct_create_8 )
	{
		logs::log() << logs::error << "In lib3d::hard::directx8::create(): DirectX is lower than 8\n";
		return;
	}

	if( !(direct3d = direct_create_8( D3D_SDK_VERSION )) )
	{
		logs::log() << logs::error << "In In lib3d::hard::directx8::create(): Failed to create Direct8 instance\n";
		return;
	}

	int adapter_count = direct3d->GetAdapterCount();
	for( int i = 0; i < adapter_count; ++i )
	{
		try
		{
			Renderer * ha = new Renderer( direct3d, i );
			renderers->push_back( ha );
			hard::Manager::add_hardware( ha );
		}
		catch( const Gluck & glu)
		{
			logs::log() << "Gluck while creating hardware: " << glu.get_description() << " at: [" << glu.get_place() << "]\n";
		}
	}
}

Creator::~Creator()
{
	while( !renderers->empty() )
	{
		Manager::remove_hardware( renderers->back() );
		delete renderers->back();
		renderers->pop_back();
	}

	logs::log() << __FUNCTION__ << "Deleting renderers\n";
	delete renderers; renderers = 0;

	int ref = 0;
	if( direct3d )
	{
		logs::log() << "direct3d->Release() ";
		ref = direct3d->Release(); direct3d = 0;
		logs::log() << "ref: " << ref << "\n";
	}
	if( d3d8_dll )
	{
		logs::log() << "FreeLibrary( d3d8_dll )\n";
		FreeLibrary( d3d8_dll ); d3d8_dll = 0;
	}
}

} // namespace directx8
} // namespace hard
} // namespace lib2d
} // namespace liba

